package com.zxb.core.util;

import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import com.zxb.core.common.User;
import org.springframework.stereotype.Component;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import cn.hutool.core.util.StrUtil;

/**
 * @author Zxb
 */
@Component
public class TokenUtil {
    private static final String ISSUER = "com.lt";
    private static final String AUDIENCE = "all";
    private static final String SUBJECT = "login";
    private static final String SECRET = "qaz@pwd2020";
    public static final Integer SAFE_TOKEN_EXPIRE = 7200;

    public static String createToken(User user) {
        Algorithm algorithm = Algorithm.HMAC256(SECRET);

        Map<String, Object> map = new HashMap<>(2);
        map.put("alg", "HS256");
        map.put("typ", "JWT");

        final long expirationTime = System.currentTimeMillis() + 7200000;

        return JWT.create()
                //签名头部
                .withHeader(map)
                //用户名
                .withClaim("username", user.getUsername())
                .withClaim("name", user.getName())
                .withClaim("id", user.getId())
                //签名发行者
                .withIssuer(ISSUER)
                //签名目的
                .withSubject(SUBJECT)
                //签名接受者
                .withAudience(AUDIENCE)
                //过期时间
                .withExpiresAt(new Date(expirationTime))
                //.withIssuedAt(nowDate)//签名的时间
                .sign(algorithm);
    }

    public static User validateToken(String token) {
        if (StrUtil.isEmpty(token)) {
            return null;
        }
        try {
            Algorithm algorithm = Algorithm.HMAC256(SECRET);
            JWTVerifier verifier = JWT.require(algorithm)
                    .withIssuer(ISSUER)
                    .withSubject(SUBJECT)
                    .withAudience(AUDIENCE)
                    .build();
            DecodedJWT jwt = verifier.verify(token);
            Map<String, Claim> claims = jwt.getClaims();
            User user = new User();
            user.setUsername(claims.get("username").asString());
            user.setName(claims.get("name").asString());
            user.setId(claims.get("id").asLong());
            return user;
        } catch (Exception e) {
            return null;
        }
    }

    public static String createSafeToken(String appKey, String appSecret) {
        Algorithm algorithm = Algorithm.HMAC256(SECRET);

        Map<String, Object> map = new HashMap<>(2);
        map.put("alg", "HS256");
        map.put("typ", "JWT");

        Calendar c = Calendar.getInstance();
        Date d1 = c.getTime();
        c.add(Calendar.SECOND, SAFE_TOKEN_EXPIRE);
        Date d2 = c.getTime();
        return JWT.create()
                //签名头部
                .withHeader(map)
                //用户名
                .withClaim("appKey", appKey)
                .withClaim("appSecret", appSecret)
                //签名发行者
                .withIssuer(ISSUER)
                //签名目的
                .withSubject(SUBJECT)
                //签名接受者
                .withAudience(AUDIENCE)
                //签名的时间
                .withIssuedAt(d1)
                //过期时间
                .withExpiresAt(d2)
                .sign(algorithm);
    }

    public static String validateSafeToken(String token) {
        if (StrUtil.isEmpty(token)) {
            return null;
        }
        try {
            Algorithm algorithm = Algorithm.HMAC256(SECRET);
            JWTVerifier verifier = JWT.require(algorithm)
                    .withIssuer(ISSUER)
                    .withSubject(SUBJECT)
                    .withAudience(AUDIENCE)
                    .build();
            DecodedJWT jwt = verifier.verify(token);
            Map<String, Claim> claims = jwt.getClaims();
            String appKey = claims.get("appKey").asString();
            String appSecret = claims.get("appSecret").asString();
            return appKey+":"+appSecret;
        } catch (Exception e) {
            return null;
        }
    }

    public static void main(String[] args) {
        User user = new User(1L, "admin", "", "系统管理员", true);
        String token = TokenUtil.createToken(user);
        System.out.println("生成token:" + token);
        User resultUser = TokenUtil.validateToken(token);
        if (resultUser != null) {
            System.out.println("解析结果:" + resultUser.getUsername());
        } else {
            System.out.println("解析异常！");
        }
    }

}
